package com.zyw.conf;

import com.zyw.auth.shiro.realm.LxbAdminRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroAuthConfig {

    @Bean("sessionIdCookie")
    public Cookie sessionIdCookie() {
        SimpleCookie cookie = new SimpleCookie();
        cookie.setHttpOnly(true);
        cookie.setMaxAge(-1);
        cookie.setName("jsessionid");
        cookie.setPath("/");
        return cookie;
    }

    /**
     * <p>shiro 会话管理</p>
     */
    @Bean("sessionManager")
    public SessionManager sessionManager() {
        DefaultWebSessionManager webSessionManager = new DefaultWebSessionManager();
        webSessionManager.setSessionIdCookie(sessionIdCookie());
        return webSessionManager;
    }

    /**
     * <p>配置核心安全事务管理器</p>
     * <p>如果有多个relam可以在此处扩展，
     * 并通过  ModularRealmAuthenticator(securityManager.authenticator) 指定认证策略(默认FirstSuccessfulStrategy) </p>
     */
    @DependsOn("lxbAdminRealm")
    @Bean(name = "securityManager")
    public SecurityManager securityManager(@Qualifier("redisCacheManager")RedisCacheManager cacheManager, @Qualifier("lxbAdminRealm") LxbAdminRealm authRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setCacheManager(cacheManager);
        securityManager.setRealm(authRealm);
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }

    /**
     * <p>ShiroFilter</p>
     * <p>直接使用ShiroFilterFactoryBean，无法自己定义UrlPattern，默认拦截 /*</p>
     * <p>如需定义拦裁，通过 FilterRegistrationBean 去注册一个 DelegatingFilterProxy</p>
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager") SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        // 配置登录的URI
        shiroFilter.setLoginUrl("/admin/unauthorized");
        shiroFilter.setUnauthorizedUrl("/admin/unauthorized");
        //配置访问权限
        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        filterChainDefinitionMap.put("/admin/login", "anon"); // 表示可以匿名访问
        filterChainDefinitionMap.put("/demo/**", "anon");
        filterChainDefinitionMap.put("/captcha/**", "anon");
        filterChainDefinitionMap.put("/**", "authc"); // 表示需要认证才可以访问

        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilter;
    }

    /**
     * 开启 Shiro Spring AOP 权限注解的支持
     */
    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @DependsOn("lifecycleBeanPostProcessor")
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(
            @Qualifier("securityManager") SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

}
